package com.goodcol.plugin.tool;

import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.util.io.FileUtil;

import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.PosixFilePermission;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

/**
 * 版权License控制类
 *
 * @author 单红宇
 * @date 2024/3/8 16:16
 */
public class DeviceTool {

    /**
     * UUID_FILE
     */
    private static final String UID_FILE = ".uid";

    /**
     * RSA-私钥
     */
    private static final String PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDVDBT1BxQv1SrqjAbS62oV2swa3RVbs4M8S4xIKgG" +
            "/ehwYq1q7GrYUxwrIebsbNAA592F76EhskiaiM/vRBzWZF2uLkWCuytfwBhANYpY2ltdtVdy0i3bEfePu9IiMsHtKMSOKrRviB3/pPT1VZnyvPO0BeUVtdrf9q6/AP" +
            "IIpTL6+Z/OjGZExDq3QB061QK6wYvw//ZqoB/t1ADzyz+n/TfH+WXmXI7DpQQCH/hufsp6S3SkM899O9Y3+4E3ifZOjOd48QXaehvyr8pXT8GlLSWEi5ZN3H9gOuAW" +
            "dfXBCSm/iVbYNbBcCkJWmLo73yN6GYYp/3lWKeySgM6BMf7/RAgMBAAECggEABGB1CkMg16o5EVw61Ci0s1n9PTSLSKjfknSpXz6orki5jMqxaJxf/v2HU87HaKPI+" +
            "Ofjg26GVV+rxkOL4fOUVu6vnYyJKFIfvU08lW/P7vNqndMIn5dpY1hEP1+b8gr6n2+yv5m2k85MYwvoZ4mdWGLHqjL1+Y2Zsk8Ng2Ui1esVdO3RiIIA626uuFonwUCG" +
            "5FuI40C6tx57uUguqMPDyUBf/TBgGlLMTi4ZJrkpqkLynjIlhRl+FXxhulMtIP+8/qHiqw8blcBACO5hnabYcHpNta+9CHu2NNQMV8qDrl16zq0HFWSNoomqG9RwZ+E" +
            "XnLyKgLfWwB2V2eMZV8kduQKBgQD8FhHA3cABNM0n+B1lIhu0Z/7PHgQFOPpbgE9n/NoGOkrKF0ZJOtuHwEgY+MOm1Xi8DnHFXkoJs47FCbBNdXeOu6mUEevOKpbBAV" +
            "sR5ir+tNfaHTCXyZUrAs8C/MnWiIpAudX9LkZeUhpXeKy4imUJ2GRK9EIRFJRbpgRvj/RjOQKBgQDYWtmLewWU8PJrVgYs5us+IyNEobP/m771312Jsvlr4hK5tEko" +
            "MbWV8rq2lbRnoxtp/RWeb7Ns5DU8kjzeYZfDSIKpSycR764CitSi8Gqtq2JN6SwKWQyTs+XvelgZztNhHJlXfMuKzPk4vG+cU5Qs7/BSGyYZ7OOhXK+6nC5JWQKBgQ" +
            "CF41LalOx9t4WfTPCP3mXIk9OKPe70tyaBosyJ9on19M/0NhhmnJQsrbudR8LiwU620xUqNsIsFOonTNYOze0KKjIPKtWLUqNvL0EnaJA9Z9+dQROmCrLnfT5l381z" +
            "3GFRr2IwbnuBbSoAe1+BREAV0pCyHrlYSQ3i/3IrrtGmQQKBgA+UIxv/BLzfyKTf8dvj2MaFozF670oVfd+YcNTMdVdGVRDYIXhqc+fTLYyeJPpdbUjpd1gMNQA/Qn" +
            "IVGZrtrg7atsXX6n1JI998/aip5RSSRabUhl5MYTJ1frYKujNJiEDy3TvGeaWJ8twZ/XNlNUMzF7vhxpGRVCa3VNP8EP0pAoGAI5jCKytf5KSlRp0ja7t0UJcN2tcO" +
            "d1x7zZYpH0j/l2zxyeVVMjsFtWbmkXm9wTcRC+mDGK+1aAhKOcTG1pEYbK2vYJf0jOL8mETRd1RWM1Q/rxa7lzBe5S4+d66NVThvatY9gcepczYRPq+NSbEcEhM9/" +
            "uEiiZ6vw110UMF06uc=";

    /**
     * DeviceTool
     */
    private DeviceTool() {
        // noImpl
    }

    /**
     * 获取UID
     *
     * @return String
     * @throws IOException IOException
     */
    public static String getUID() throws IOException {
        Path uuidFilePath = PathManager.getCommonDataPath().resolve(UID_FILE);
        File uuidFile = uuidFilePath.toFile();
        String uuidString;
        if (!uuidFile.exists()) {
            if (!uuidFile.createNewFile()) {
                NotificationUtils.showInfoNotification("File creation failed, path = " + uuidFilePath.toAbsolutePath());
                return null;
            }
            // 初始化文件内容
            uuidString = UUID.randomUUID().toString();
            FileUtil.writeToFile(uuidFile, uuidString);
            setFileAttr(uuidFilePath);
        } else {
            // 读取文件内容
            uuidString = FileUtil.loadFile(uuidFile).trim();
        }
        BasicFileAttributes attr = Files.readAttributes(uuidFilePath, BasicFileAttributes.class);
        // 读取文件创建时间
        FileTime fileCreateTime = attr.creationTime();
        // 最后返回创建时间+UUID拼接后的MD5
        return md5(fileCreateTime.toString().concat(uuidString));
    }

    /**
     * setFileReadOnly
     *
     * @param filePath filePath
     */
    private static void setFileAttr(Path filePath) {
        String osName = System.getProperty("os.name").toLowerCase();
        try {
            if (osName.contains("win")) { // Windows 系统
                // 在 Windows 上，我们可以通过 Files.setAttribute 来设置 dos:readonly 属性
                Files.setAttribute(filePath, "dos:readonly", true);
                Files.setAttribute(filePath, "dos:hidden", true);
            } else { // Unix-like 系统 (Linux, macOS)
                // 在 Unix-like 系统上，我们使用 PosixFilePermissions 来设置只读权限
                Set<PosixFilePermission> perms = new HashSet<>();
                // 添加所有者的读权限
                perms.add(PosixFilePermission.OWNER_READ);
                // 如果需要，也可以添加其他权限，但为了只读，这里只添加读权限
                Files.setPosixFilePermissions(filePath, perms);
            }
        } catch (Exception e) {
            // not impl
        }
    }

    /**
     * md5
     *
     * @param input input
     * @return String
     */
    public static String md5(String input) {
        try {
            // 获取MessageDigest实例并指定MD5算法
            MessageDigest md = MessageDigest.getInstance("MD5");

            // 将输入字符串转换为字节数组，并进行哈希计算
            byte[] messageDigest = md.digest(input.getBytes(StandardCharsets.UTF_8));

            // 将哈希后的二进制数据转换为16进制表示形式
            BigInteger no = new BigInteger(1, messageDigest);
            StringBuilder hashText = new StringBuilder(no.toString(16));

            // 补零至32位长度
            while (hashText.length() < 32) {
                hashText.insert(0, "0");
            }
            return hashText.toString().toUpperCase();
        } catch (NoSuchAlgorithmException e) {
            return "";
        }
    }

    /**
     * 获取设备唯一ID
     *
     * @return 设备唯一ID
     */
    public static String getDeviceId() {
        try {
            return getUID();
        } catch (IOException e) {
            NotificationUtils.showInfoNotification(e.getMessage());
            return null;
        }
    }

    /**
     * 返回匹配到的网卡的mac地址的加密格式
     * 尽可能排除掉虚拟网卡
     *
     * @return String
     */
    public static List<String> getMacEncodedList() {
        try {
            List<NetworkInterface> niList = getNetworkInterfaces();
            List<String> retList = new ArrayList<>();
            // 对niList进行排序，将en开头、eth开头、wlan开头的放在最前面
            niList.sort(DeviceTool::networkInterfaceCompare);
            if (!niList.isEmpty()) {
                for (NetworkInterface networkInterface : niList) {
                    byte[] hardwareAddress = networkInterface.getHardwareAddress();
                    if (hardwareAddress.length == 0) {
                        continue;
                    }
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0, j = hardwareAddress.length; i < j; i++) {
                        sb.append(String.format("%02X%s", hardwareAddress[i], (i < j - 1 ? "-" : "")));
                    }
                    // 这里对mac进行md5返回
                    retList.add(DeviceTool.md5(sb.toString().toUpperCase().trim()));
                }
            }
            return retList;
        } catch (SocketException e) {
            return null;
        }
    }

    /**
     * getNetworkInterfaces
     *
     * @return List
     * @throws SocketException SocketException
     */
    private static List<NetworkInterface> getNetworkInterfaces() throws SocketException {
        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
        List<NetworkInterface> niList = new ArrayList<>();
        while (networkInterfaces.hasMoreElements()) {
            NetworkInterface ni = networkInterfaces.nextElement();
            // 尽可能排除虚拟网卡、蓝牙网卡（以及其他非物理接口）
            String niStr = ni.toString().toLowerCase();
            boolean ignoreNi = (ni.isLoopback() || ni.isVirtual() || ni.getMTU() <= 0
                    || !niStr.matches("^(?!.*(?:bluetooth|vm|vpn|virtual)).*$")
                    || ni.getHardwareAddress() == null);
            if (!ignoreNi) {
                niList.add(ni);
            }
        }
        return niList;
    }

    /**
     * networkInterfaceCompare
     *
     * @param ni1 ni1
     * @param ni2 ni2
     * @return data
     */
    private static int networkInterfaceCompare(NetworkInterface ni1, NetworkInterface ni2) {
        String ni1Name = ni1.getName().toLowerCase();
        String ni2Name = ni2.getName().toLowerCase();
        boolean isEn1 = ni1Name.startsWith("en");
        boolean isEn2 = ni2Name.startsWith("en");
        boolean isEth1 = ni1Name.startsWith("eth");
        boolean isEth2 = ni2Name.startsWith("eth");
        boolean isWlan1 = ni1Name.startsWith("wlan");
        boolean isWlan2 = ni2Name.startsWith("wlan");

        // 如果两者前缀匹配相同，"en"、"eth"、”wlan"开头，则自然排序
        if ((isEn1 && isEn2) || (isEth1 && isEth2) || (isWlan1 && isWlan2)) {
            return ni1Name.compareTo(ni2Name);
        }

        // "en"、"eth"、"wlan"开头的排在其他类型的前面
        if (isEn1 || isEn2) {
            return isEn1 ? -1 : 1;
        } else if (isEth1 || isEth2) {
            return isEth1 ? -1 : 1;
        } else if (isWlan1 || isWlan2) {
            return isWlan1 ? -1 : 1;
        } else {
            // 非特定前缀开头的按自然顺序
            return ni1Name.compareTo(ni2Name);
        }
    }

}
